package agu.widget;

import agu.builtin.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;

public class ListView extends RecyclerView
{
    public int spanCount;
    public int spanCount2;
    public float spanSize;

    public Adapter2 adapter2 = new Adapter2();

    private List<View> inflatedViews;

    public ListView(@NonNull Context context){
        super(context);
        init(context, null);
    }

    public ListView(@NonNull Context context, @Nullable AttributeSet attrs){
        super(context, attrs);
        init(context, attrs);
    }

    public ListView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr){
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs){
        if(attrs != null){
            TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ListView);
            spanCount = a.getInt(R.styleable.ListView_spanCount, 0);
            spanCount2 = a.getInt(R.styleable.ListView_spanCount2, 0);
            spanSize = a.getDimension(R.styleable.ListView_spanSize, 0);
            adapter2.itemLayout = a.getResourceId(R.styleable.ListView_itemLayout, 0);
            a.recycle();
        }
        setAdapter(adapter2);
    }

    @Override
    protected void onMeasure(int widthSpec, int heightSpec){
        disposeInflatedViews();

        super.onMeasure(widthSpec, heightSpec);

        if(getLayoutManager() instanceof GridLayoutManager){
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();

            int spanCount;
            if(spanSize > 0){
                spanCount = (int)(width / spanSize);
            }else{
                spanCount = width > height && spanCount2 > 0? spanCount2: this.spanCount;
            }
            if(spanCount < 1) spanCount = 1;

            ((GridLayoutManager)getLayoutManager()).setSpanCount(spanCount);
        }
    }

    @Override
    public void setAdapter(@Nullable Adapter adapter){
        disposeInflatedViews();
        super.setAdapter(adapter);
    }

    private void disposeInflatedViews(){
        if(inflatedViews == null){
            return;
        }
        for(View view: inflatedViews) removeView(view);

        boolean inEditMode = isInEditMode();
        if(inEditMode){
            LinearLayout linearLayout = new LinearLayout(getContext());
            if(getLayoutManager() == null || getLayoutManager().canScrollVertically()){
                linearLayout.setOrientation(LinearLayout.VERTICAL);
            }
            for(View view: inflatedViews) linearLayout.addView(view);

            ViewGroup parent = (ViewGroup)getParent();
            int index = parent.indexOfChild(this);
            parent.removeViewAt(index);
            parent.addView(linearLayout, index);
        }

        inflatedViews = null;
    }

    @Override
    protected ViewGroup.LayoutParams generateDefaultLayoutParams(){
        fixLayoutManager();
        return super.generateDefaultLayoutParams();
    }

    @Override
    public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs){
        fixLayoutManager();
        return super.generateLayoutParams(attrs);
    }

    @Override
    protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p){
        fixLayoutManager();
        return super.generateLayoutParams(p);
    }

    public void fixLayoutManager(){
        if(getLayoutManager() == null){
            setLayoutManager(new LinearLayoutManager(getContext()));
        }
    }

    @Override
    protected void onFinishInflate(){
        super.onFinishInflate();

        int count = getChildCount();
        if(count == 0) return;

        if(inflatedViews == null) inflatedViews = new ArrayList<>(count);
        else inflatedViews.clear();
        for(int i = 0; i < count; i++) inflatedViews.add(getChildAt(i));
        //removeAllViews();

        adapter2.itemList = inflatedViews;
    }

    public static class ViewHolder2 extends ViewHolder
    {
        public ViewHolder2(@NonNull View itemView){
            super(itemView);
        }
    }

    public static class Adapter2 extends Adapter<ViewHolder> implements View.OnClickListener
    {
        public interface OnClick
        {
            void onClick(View v, int position);
        }

        private OnClick onClick;

        public interface OnBind
        {
            void onBind(Adapter2 adapter, ViewHolder vh, int position, List<Object> payloads);
        }

        private OnBind onBind;

        public int itemLayout = -1;

        public int itemCount = 0;

        public List itemList;

        @Override
        public int getItemCount(){
            return itemCount = itemList != null? itemList.size(): itemCount;
        }

        @Override
        public int getItemViewType(int position){
            Object item = itemList == null? null: itemList.get(position);
            if(item instanceof View){
                return position;
            }
            if(item instanceof Integer){
                return (int)item;
            }
            return itemLayout;
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int type){
            View view = null;
            if(type >= 0 && itemList != null && type < itemList.size()){
                Object item = itemList.get(type);
                if(item instanceof View) view = (View)item;
            }
            if(view == null){
                view = LayoutInflater.from(parent.getContext()).inflate(type, parent, false);
            }
            return new ViewHolder2(view);
        }

        public Adapter2 setOnBind(OnBind onBind){
            this.onBind = onBind;
            return this;
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder vh, int position,
            @NonNull List<Object> payloads){
            if(onBind != null){
                onBind.onBind(this, vh, position, payloads);
            }
            super.onBindViewHolder(vh, position, payloads);
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder vh, int position){
        }

        @Override
        public void onViewRecycled(@NonNull ViewHolder holder){
            super.onViewRecycled(holder);
        }

        public Adapter2 setOnClick(OnClick onClick){
            this.onClick = onClick;
            return this;
        }

        @Override
        public void onClick(View v){
            if(onClick != null){
                ViewHolder vh = findViewHolder(this, v);
                int position = vh == null? -1: vh.getAdapterPosition();
                onClick.onClick(v, position);
            }
        }

        public static ViewHolder findViewHolder(Adapter<?> adapter, View view){
            while(view != null){
                ViewParent parent = view.getParent();
                if(parent instanceof RecyclerView &&
                    ((RecyclerView)parent).getAdapter() == adapter){
                    return ((RecyclerView)parent).getChildViewHolder(view);
                }
                view = parent instanceof View? (View)parent: null;
            }
            return null;
        }

    }
}
